package com.leonzhangxf.spel.reference;

import com.leonzhangxf.spel.reference.bean.Inventor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Variables
 * <p>
 * You can reference variables in the expression by using the #variableName syntax.
 * Variables are set by using the setVariable method on EvaluationContext implementations.
 *
 * @author leonzhangxf
 * @date 20190427
 */
public class Variables {

    public static void main(String[] args) {
        SpelParserConfiguration parserConfiguration =
            new SpelParserConfiguration(true, true);
        SpelExpressionParser parser = new SpelExpressionParser(parserConfiguration);

        Inventor tesla = new Inventor("Nikola Tesla", "Serbian");

        EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        context.setVariable("newName", "Mike Tesla");

        parser.parseExpression("Name = #newName").getValue(context, tesla);
        // "Mike Tesla"
        System.out.println(tesla.getName());

        System.out.println("================================");
        thisAndRoot();
    }

    /**
     * The #this and #root Variables
     * <p>
     * The #this variable is always defined and refers to the current evaluation object
     * (against which unqualified references are resolved).
     * <p>
     * The #root variable is always defined and refers to the root context object.
     * Although #this may vary as components of an expression are evaluated,
     * #root always refers to the root.
     */
    @SuppressWarnings("unchecked")
    private static void thisAndRoot() {
        // create an array of integers
        List<Integer> primes = new ArrayList<>(Arrays.asList(2, 3, 5, 7, 11, 13, 17));

        // create parser and set variable 'primes' as the array of integers
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        context.setVariable("primes", primes);

        // all prime numbers > 10 from the list (using selection ?{...})
        // evaluates to [11, 13, 17]
        List<Integer> primesGreaterThanTen = (List<Integer>) parser
            .parseExpression("#primes.?[#this>10]").getValue(context);
        System.out.println(primesGreaterThanTen);
    }
}
